﻿package com.zouloux.core.base
{
	import com.zouloux.core.debug.Debug;
	import com.zouloux.core.IDisposable;
	import flash.display.MovieClip;
	import flash.display.Sprite;
	import flash.display.Stage;
	import flash.display.StageAlign;
	import flash.display.StageScaleMode;
	import flash.events.Event;
	import flash.events.MouseEvent;
	import flash.system.Capabilities;
	import flash.system.Security;
	import flash.system.System;
	
	/**
	 * ...
	 * @author ZoulouX
	 */
	public class DocumentBase extends MovieClipBase implements IMovieClipBase, IDisposable
	{
		/**
		 * L'instance du DocumentBase
		 */
		private static var __instance				:DocumentBase;
		
		/**
		 * Récupérer l'instance du DocumentBase
		 */
		public static function get instance ():DocumentBase
		{
			return __instance;
		}
		
		/**
		 * Récupérer le stage
		 */
		public static function get stage ():Stage
		{
			return __instance.stage;
		}
		
		/**
		 * Vérifier si le player est debug ou release
		 */
		public static function get isDebug ():Boolean
		{
			return Capabilities.isDebugger;
		}
		
		/**
		 * Vérifier si le player est exécuté en local
		 */
		public static function get isLocal ():Boolean
		{
			return (Capabilities.playerType == "StandAlone");
		}
		
		/**
		 * Savoir si l'application est chargée
		 */
		public static function get isLoaded ():Boolean
		{
			return instance._loaded;
		}
		
		/**
		 * Récupérer l'utilisation mémoire
		 */
		public static function get memoryUsed ():Number
		{
			return System.totalMemory;
		}
		
		/**
		 * Récupérer le chargement entre 0 et 1
		 */
		public static function get progress ():Number
		{
			if (stage.loaderInfo.bytesLoaded > 0 && stage.loaderInfo.bytesTotal > 0)
				return stage.loaderInfo.bytesLoaded / stage.loaderInfo.bytesTotal;
			else
				return 0;
		}
		
		/**
		 * La version du player
		 */
		protected var _version			:Number;
		
		/**
		 * Le type de plateforme
		 */
		protected var _platform			:String;
		
		/**
		 * Savoir si l'application est chargée
		 */
		protected var _loaded			:Boolean 			= false;
		
		/**
		 * Savoir si le curseur est au dessus de l'application
		 */
		protected var _mouseOver		:Boolean			= false;
		
		/**
		 * Les paramètres
		 */
		protected var _parameters		:Object				= {};
		
		/**
		 * Savoir si on doit redimensionner le stage
		 */
		protected var _uiStage			:Boolean;
		
		/**
		 * Récupérer les paramètres
		 */
		public function get parameters ():Object
		{
			return _parameters;
		}
		
		/**
		 * Définir les paramètres
		 */
		public function set parameters (value:Object):void 
		{
			_parameters = value;
		}
		
		/**
		 * Récupérer la version du Flash Player
		 */
		public function get version ():Number
		{
			return _version;
		}
		
		/**
		 * Récupérer la plateforme
		 */
		public function get platform ():String
		{
			return _platform;
		}
		
		/**
		 * Récupérer la largeur du stage
		 */
		override public function get width ():Number
		{
			return stage.stageWidth;
		}
		
		/**
		 * Récupérer la hauteur du stage
		 */
		override public function get height ():Number
		{
			return stage.stageHeight;
		}
		
		/**
		 * Le constructeur du DocumentBase
		 * @param	pChild : La classe fille au DocumentBase, pour être stockée dans le singleton
		 */
		public function DocumentBase (pChild:DocumentBase = null, pUiStage:Boolean = false)
		{
			Debug.add("ZoulouX AS3 Framework 0.4");
			
			// Récupérer la plateforme et la version
			var v:String = Capabilities.version;
			
			// Séparer la plateforme de la version
			var pAndV:Array = v.split(" ");
			
			// Enregistrer la plateforme
			_platform = pAndV[0];
			
			// Convertir la version en Number et l'enregistrer
			_version = parseFloat(pAndV[1].split(",", 2).join("."));
			
			// Enregistrer la variable de l'uiStage
			_uiStage = pUiStage;
			
			// Mémoriser l'instance
			__instance = (pChild != null ? pChild : this);
			
			// Ecouter la fin du chargement
			loaderInfo.addEventListener(Event.COMPLETE, loadedHandler);
			
			// Relayer la construction
			super();
		}
		
		/**
		 * Initialisation de l'application, ajout au stage
		 * @param	event
		 */
		override protected function initHandler(event:Event = null):void
		{
			// Relayer l'appel
			super.initHandler();
			
			// Ecouter les mouvements de la souris
			stage.addEventListener(Event.MOUSE_LEAVE, mouseLeaveHandler);
			stage.addEventListener(MouseEvent.MOUSE_MOVE, mouseMoveHandler);
			stage.addEventListener(Event.RESIZE, resizeHandler);
			
			// Le comportement du stage
			if (_uiStage)
			{
				stage.align = StageAlign.TOP_LEFT;
				stage.scaleMode = StageScaleMode.NO_SCALE;
			}
		}
		
		/**
		 * Chargement terminé
		 * @param	event
		 */
		private function loadedHandler (event:Event = null):void 
		{
			// Ne plus écouter
			loaderInfo.removeEventListener(Event.COMPLETE, loadedHandler);
			
			// C'est chargé
			_loaded = true;
			
			// Appeler la méthode publique
			loaded();
		}
		
		/**
		 * Le curseur quitte la scène
		 * @param	event
		 */
		private function mouseLeaveHandler (event:Event):void
		{
			// La souris n'est plus au dessus
			_mouseOver = false;
			
			// Appleler la méthode publique
			mouseOut();
			
			// Ecouter les mouvements
			stage.addEventListener(MouseEvent.MOUSE_MOVE, mouseMoveHandler);
		}
		
		/**
		 * Le curseur bouge sur la scène
		 * @param	event
		 */
		private function mouseMoveHandler (event:MouseEvent):void
		{
			// La souris est au dessus
			_mouseOver = true;
			
			// Appeler la méthode publique
			mouseIn();
			
			// Ne plus écouter
			stage.removeEventListener(MouseEvent.MOUSE_MOVE, mouseMoveHandler);
		}
		
		/**
		 * Redimentionnement du stage
		 */
		private function resizeHandler (event:Event):void
		{
			resize();
		}
		
		/**
		 * Chargement terminé
		 * Méthode à overrider, appelée lorsque l'application totalement chargée
		 * @param	event : L'event associé
		 */
		public function loaded ():void
		{
			
		}
		
		/**
		 * Méthode à overrider, appelée lorsque le curseur quitte l'application flash
		 * @param	event
		 */
		public function mouseOut ():void
		{
			
		}
		
		/**
		 * Méthode à overrider, appelée lorsque le curseur entre dans l'application flash
		 */
		public function mouseIn ():void
		{
			
		}
		
		/**
		 * Redimentionnement du stage
		 */
		public function resize ():void
		{
			
		}
		
		/**
		 * Le clip est effacé depuis son parent
		 */
		override protected function disposeHandler (event:Event = null):void
		{
			// Relayer l'appel
			super.disposeHandler();
			
			// Supprimer tous les listeners locaux
			stage.removeEventListener(Event.MOUSE_LEAVE, mouseLeaveHandler);
			stage.removeEventListener(Event.RESIZE, mouseLeaveHandler);
			stage.removeEventListener(MouseEvent.MOUSE_MOVE, mouseMoveHandler);
			loaderInfo.removeEventListener(Event.COMPLETE, loadedHandler);
		}
	}
}